Skip to content

Conversation

@pkhry
Copy link

@pkhry pkhry commented Nov 5, 2025

Description

move away from thread-local.
see #286

Notes

  • where possible using ext.start_transaction ext.rollback_transaction to save up time on cloning.
  • Log ordering changed according to the issue referenced by pallet-revive CallLog docs
  • pallet-revive state modifications mostly moved to crates/revive-strategy/state.rs, revm modifications happen through default cheatcode handlers in foundry.
  • added one more log order test

alexggh and others added 30 commits October 2, 2025 12:34
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Signed-off-by: Alexandru Gheorghe <[email protected]>
Copy link

@alexggh alexggh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks alright to me, good job.

} else {
// Else, we pop the front element
return_data_queue.pop_front()
} {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cargo fmt or what ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clippy lint application

pkhry and others added 2 commits November 20, 2025 17:08
@pkhry pkhry force-pushed the pkhry/refactor_externalities_usage branch from 59da939 to bbc4cb2 Compare November 20, 2025 16:09
}
}

// Sync REVM state back to pallet-revive if this call was executed in REVM
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try to run the storage migration test:

function testStorageMigration() public {
        SimpleStorage storageContract = new SimpleStorage();

        // Mark the contract as persistent so it migrates
        vm.makePersistent(address(storageContract));

        storageContract.set(42);
        assertEq(storageContract.get(), 42);

        vm.pvm(false);

        assertEq(storageContract.get(), 42);

        storageContract.set(100);
        assertEq(storageContract.get(), 100);

        vm.pvm(true);
        assertEq(storageContract.get(), 100);
    }

I think it will fail without this code.

Copy link
Author

@pkhry pkhry Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it indeed does.
However, if we move storage migration code inside select_revive to always migrate code then it does work.

also why do we need makePersistent? its purely a fork related cheatcode

edit:
makePersistent is a discount vm.register

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can put the storage migration code there, but I think we may have the issue with performance. You will need to sync all contracts - you do not have info which slot was modified.
Regarding makePersistent we used the same approach that zksync uses in select vm. They migrate persistent account as I remember. Maybe due to performance?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can put the storage migration code there, but I think we may have the issue with performance.

i'll post the benchmarks on morpho test-suite, but it's definitely not the bottle neck as it could be visible there

You will need to sync all contracts - you do not have info which slot was modified.

we can use slot.is_cold() or compare the revm's slot value to current slot value before doing a write, but i doubt that will help with performance as we will still hash the key twice both for read and write

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you won’t see it in this test suite because the migration runs only once at the beginning, and all contracts with slots are migrated then (they are all newly created). The performance impact should become noticeable when you switch between EVMs many times — at that point it will be painful, because you will need to loop over all contract slots again and again.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will impact fuzz tests when such cheatcode will be present.
I was thinking of having symmetric solution to this what we have with tracer when we are doing state migration from Revive to REVM. In this case we could skip all cheatcodes custom implementation which modify the storage and use the default implementation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will impact fuzz tests when such cheatcode will be present.

why would anyone go out their way to switch vm's in a lot of the fuzz tests?

In this case we could skip all cheatcodes custom implementation which modify the storage and use the default implementation.

not quite ass you'll need to migrate state slots for every contract touched during the test each time any cheatcode is called

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is that it is always a trade-off between doing things incrementally or as one large operation. Following this direction, we could also skip applying slot changes from the tracer in post_exec.
I prefer incremental changes, but it is OK for now.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it stands now if we remove state change functionality from the strategy and rely on duplicating the state via apply_revm_diff we would do the whole select_pvm thing on every cheatcode call to update the state on pallet_revive side of things

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it is a problem, I had such PR but due to performance issues I put it on hold. We would need to have just list of changes.

@pkhry pkhry requested a review from smiasojed November 20, 2025 20:38
Copy link

@filip-parity filip-parity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This refactoring should also solve DuplicateContract issues on macOS. Good job!

@smiasojed
Copy link
Collaborator

smiasojed commented Nov 21, 2025

This also does not work, probably we need to migrate full state in select_evm anyway or do initial migration and later on incremental in both directions.

contract Storage {
    uint256 public slot0 = 10;
    uint256 public slot1 = 20;
    function setSlot0(uint256 value) public {
        slot0 = value;
    }
    
    function setSlot1(uint256 value) public {
        slot1 = value;
    }
}

contract StoreTest is DSTest {
    Vm constant vm = Vm(HEVM_ADDRESS);
    Storage store;

    function setUp() public {
        vm.pvm(true);
        store = new Storage();
        vm.makePersistent(address(store));
    }

    function testStoregeMigrationWorks() public {
        assertEq(store.slot0(), 10, "initial value for slot 0 is incorrect");
        assertEq(store.slot1(), 20, "initial value for slot 1 is incorrect");
        vm.store(address(store), bytes32(0), bytes32(uint256(1)));
        vm.pvm(false);
        assertEq(store.slot0(), 1, "store failed");
        assertEq(store.slot1(), 20, "store failed");
    }

    function testStoregeMigration2Works() public {
        assertEq(store.slot0(), 10, "initial value for slot 0 is incorrect");
        assertEq(store.slot1(), 20, "initial value for slot 1 is incorrect");
        store.setSlot0(1);
        vm.pvm(false);
        assertEq(store.slot0(), 1, "store failed");
        assertEq(store.slot1(), 20, "store failed");
    }
    }

It is not related to your changes, so we can address it as follow up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants